package luj.tool.jnproxyan.proxy.util.data.load;

import luj.data.api.Data;
import luj.data.api.DataContext;
import luj.tool.jnproxyan.proxy.database.DatabaseState;
import luj.tool.jnproxyan.proxy.util.data.DataDirtySaver;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.Table;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class DataGlobalLoader {

  public DataGlobalLoader inject(Class<?> type, DatabaseState dbState, Map<String, Data> loadCache) {
    DataGlobalLoader result = new DataGlobalLoader();
    result._type = type;
    result._loadCache = loadCache;
    result._dbState = dbState;
    result._jooq = dbState.getJooq();

    result._lujdata = _lujdata;
    result._byIdLoader = _byIdLoader;

    return result;
  }

  public Data loadOrCreate() {
    Record result = _jooq.select(F_ID)
        .from(T_DATA)
        .where(F_TABLE.eq(_type.getName()))
        .fetchAny();

    if (result == null) {
      return createNew();
    }

    Long dataId = result.get(F_ID);
    return _byIdLoader.inject(_type, dataId, _dbState, _loadCache).load();
  }

  private Data createNew() {
    Long dataId = _dbState.getNextId().getAndIncrement();
    Data data = makeData(dataId);

    _jooq.insertInto(T_DATA, F_ID, F_TABLE, F_DATA).values(dataId, _type.getName(), "{}").execute();
    return data;
  }

  private Data makeData(Long id) {
    Data data = _lujdata.createData(id);
    data.setType(_dbState.getDataTypes().getType(_type));
    return data;
  }

  private static final Table<Record> T_DATA = DataDirtySaver.T_DATA;
  private static final Table<Record> T_DATAN = DataDirtySaver.T_DATAN;

  private static final Field<Long> F_ID = DataDirtySaver.F_ID;
  private static final Field<String> F_TABLE = DataDirtySaver.F_TABLE;
  private static final Field<String> F_DATA = DataDirtySaver.F_DATA;
  private static final Field<Long> F_PARENT = DataDirtySaver.F_PARENT;

  Class<?> _type;
  DSLContext _jooq;

  DatabaseState _dbState;
  Map<String, Data> _loadCache;

  @Autowired
  DataContext _lujdata;

  @Autowired
  DataByIdLoader _byIdLoader;
}
